package ast

import (
	"testing"
)

func TestStringLiteral(t *testing.T) {
	sl := &StringLiteral{Value: "hello world"}
	expected := `"hello world"`
	
	if sl.String() != expected {
		t.Errorf("expected %s, got %s", expected, sl.String())
	}
}

func TestSymbol(t *testing.T) {
	sym := &Symbol{Value: "test-symbol"}
	expected := "test-symbol"
	
	if sym.String() != expected {
		t.Errorf("expected %s, got %s", expected, sym.String())
	}
}

func TestList(t *testing.T) {
	elements := []Expression{
		&Symbol{Value: "define"},
		&Symbol{Value: "x"},
		&StringLiteral{Value: "test"},
	}
	
	list := &List{Elements: elements}
	expected := "(define x \"test\")"
	
	if list.String() != expected {
		t.Errorf("expected %s, got %s", expected, list.String())
	}
}

func TestDefineExpr(t *testing.T) {
	define := &DefineExpr{
		Name:  Symbol{Value: "my-var"},
		Value: &StringLiteral{Value: "hello"},
	}
	
	expected := "(define my-var \"hello\")"
	if define.String() != expected {
		t.Errorf("expected %s, got %s", expected, define.String())
	}
}

func TestDisplayExpr(t *testing.T) {
	display := &DisplayExpr{
		Value: &StringLiteral{Value: "hello world"},
	}
	
	expected := "(display \"hello world\")"
	if display.String() != expected {
		t.Errorf("expected %s, got %s", expected, display.String())
	}
}

func TestProgram(t *testing.T) {
	program := &Program{
		Expressions: []Expression{
			&DefineExpr{
				Name:  Symbol{Value: "x"},
				Value: &StringLiteral{Value: "test"},
			},
			&DisplayExpr{
				Value: &Symbol{Value: "x"},
			},
		},
	}
	
	result := program.String()
	expected := `(define x "test")
(display x)
`
	
	if result != expected {
		t.Errorf("expected:\n%s\ngot:\n%s", expected, result)
	}
}

func TestEmptyList(t *testing.T) {
	list := &List{Elements: []Expression{}}
	expected := "()"
	
	if list.String() != expected {
		t.Errorf("expected %s, got %s", expected, list.String())
	}
}

func TestNestedList(t *testing.T) {
	nested := &List{
		Elements: []Expression{
			&Symbol{Value: "outer"},
			&List{
				Elements: []Expression{
					&Symbol{Value: "inner"},
					&StringLiteral{Value: "nested"},
				},
			},
		},
	}
	
	expected := "(outer (inner \"nested\"))"
	if nested.String() != expected {
		t.Errorf("expected %s, got %s", expected, nested.String())
	}
}